using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Terra.Core.Common.ApiResponse;
using Terra.Core.Common.ErrorCodes.Constants;
using Terra.Core.Common.Exceptions;
using Terra.Core.Common.Models.Pagination;
using Terra.Data.Entities.Identity;
using Terra.Data.Models.Identity;
using Terra.Data.Repository.Identity;
using Terra.Data.UnitOfWork;
using Terra.Service.Common.Base;
using Terra.Service.Identity.Interfaces;
using Microsoft.Extensions.Logging;

namespace Terra.Service.Identity.Implementations;

/// <summary>
/// 角色服务实现
/// </summary>
public class RoleService : AppServiceBase, IRoleService
{
    private readonly IRoleRepository _roleRepository;
    private readonly IPermissionRepository _permissionRepository;
    private readonly ILogger<RoleService> _logger;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="unitOfWork">工作单元</param>
    /// <param name="roleRepository">角色仓储</param>
    /// <param name="permissionRepository">权限仓储</param>
    /// <param name="mapper">对象映射器</param>
    /// <param name="logger">日志记录器</param>
    public RoleService(
        IUnitOfWork unitOfWork,
        IRoleRepository roleRepository,
        IPermissionRepository permissionRepository,
        IMapper mapper,
        ILogger<RoleService> logger) : base(unitOfWork, mapper)
    {
        _roleRepository = roleRepository ?? throw new ArgumentNullException(nameof(roleRepository));
        _permissionRepository = permissionRepository ?? throw new ArgumentNullException(nameof(permissionRepository));
        _logger = logger;
    }

    /// <summary>
    /// 获取角色
    /// </summary>
    /// <param name="id">角色ID</param>
    /// <returns>角色实体</returns>
    public async Task<ApiResponse<Role>> GetRoleAsync(Guid id)
    {
        var role = await _roleRepository.GetByIdAsync(id);
        if (role == null)
        {
            return ApiResponse<Role>.Error(SecurityErrorCodes.ROLE_NOT_FOUND);
        }
        return ApiResponse<Role>.Success(role);
    }

    /// <summary>
    /// 分页查询角色
    /// </summary>
    /// <param name="query">查询条件</param>
    /// <returns>分页结果</returns>
    public async Task<ApiResponse<PagedList<RoleItemDto>>> GetPagedRolesAsync(RoleQueryDto query)
    {
        // 获取分页数据
        var (roles, totalCount) = await _roleRepository.GetPagedRolesAsync(query);

        // 转换为DTO
        var roleItems = Mapper.Map<List<RoleItemDto>>(roles);

        // 创建分页结果
        var pagedList = new PagedList<RoleItemDto>(
            roleItems,
            totalCount,
            query.PageIndex,
            query.PageSize);

        return ApiResponse<PagedList<RoleItemDto>>.Success(pagedList);
    }

    /// <summary>
    /// 获取角色详情
    /// </summary>
    /// <param name="id">角色ID</param>
    /// <returns>角色详情</returns>
    public async Task<ApiResponse<RoleDetailDto>> GetRoleDetailAsync(Guid id)
    {
        var role = await _roleRepository.GetByIdAsync(id);
        if (role == null)
        {
            throw new BusinessException("角色不存在", SecurityErrorCodes.ROLE_NOT_FOUND);
        }

        var roleDto = Mapper.Map<RoleDetailDto>(role);

        // 获取角色的权限ID列表
        roleDto.PermissionIds = await _roleRepository.GetRolePermissionIdsAsync(id);

        return ApiResponse<RoleDetailDto>.Success(roleDto);
    }

    /// <summary>
    /// 创建角色
    /// </summary>
    /// <param name="dto">创建参数</param>
    /// <returns>创建结果</returns>
    public async Task<ApiResponse<Guid>> CreateRoleAsync(RoleCreateDto dto)
    {
        // 验证角色名唯一性
        if (await _roleRepository.ExistsByNameAsync(dto.Name))
        {
            throw new BusinessException("角色名称已存在", SecurityErrorCodes.ROLE_NAME_ALREADY_EXISTS);
        }

        // 验证权限是否存在
        if (dto.PermissionIds?.Any() == true)
        {
            foreach (var permissionId in dto.PermissionIds)
            {
                if (!await _permissionRepository.ExistsAsync(p => p.Id == permissionId))
                {
                    throw new BusinessException($"权限ID {permissionId} 不存在",
                        SecurityErrorCodes.PERMISSION_NOT_FOUND);
                }
            }
        }

        try
        {
            // 创建角色
            var role = Mapper.Map<Role>(dto);
            role.Id = Guid.NewGuid();
            role.NormalizedName = dto.Name.ToUpperInvariant();
            role.ConcurrencyStamp = Guid.NewGuid().ToString();
            // 使用执行策略包装事务操作
            var strategy = UnitOfWork.CreateExecutionStrategy();
            await strategy.ExecuteAsync(async () =>
            {
                await UnitOfWork.BeginTransactionAsync();

                role = await _roleRepository.InsertAsync(role);

                // 保存权限关联
                if (dto.PermissionIds?.Any() == true)
                {
                    await _roleRepository.SaveRolePermissionsAsync(role.Id, dto.PermissionIds);
                }

                await UnitOfWork.CommitTransactionAsync();
                
            });
            return ApiResponse<Guid>.Success(role.Id);

        }
        catch (Exception ex)
        {
            await UnitOfWork.RollbackTransactionAsync();
            _logger.LogError(ex, "创建角色异常");
            throw;
        }
    }

    /// <summary>
    /// 更新角色
    /// </summary>
    /// <param name="dto">更新参数</param>
    /// <returns>更新结果</returns>
    public async Task<ApiResponse> UpdateRoleAsync(RoleUpdateDto dto)
    {
        // 获取角色
        var role = await _roleRepository.GetByIdAsync(dto.Id);
        if (role == null)
        {
            throw new BusinessException("角色不存在", SecurityErrorCodes.ROLE_NOT_FOUND);
        }

        //// 系统角色不允许修改
        //if (role.IsSystem)
        //{
        //    throw new BusinessException("系统角色不允许修改", SecurityErrorCodes.SYSTEM_ROLE_MODIFY_FORBIDDEN);
        //}

        // 验证角色名唯一性
        if (await _roleRepository.ExistsByNameAsync(dto.Name, dto.Id))
        {
            throw new BusinessException("角色名称已存在", SecurityErrorCodes.ROLE_NAME_ALREADY_EXISTS);
        }

        // 验证权限是否存在
        if (dto.PermissionIds?.Any() == true)
        {
            foreach (var permissionId in dto.PermissionIds)
            {
                if (!await _permissionRepository.ExistsAsync(p => p.Id == permissionId))
                {
                    throw new BusinessException($"权限ID {permissionId} 不存在",
                        SecurityErrorCodes.PERMISSION_NOT_FOUND);
                }
            }
        }

        try
        {
            // 使用执行策略包装事务操作
            var strategy = UnitOfWork.CreateExecutionStrategy();
            await strategy.ExecuteAsync(async () =>
            {
                await UnitOfWork.BeginTransactionAsync();
                try
                {
                    // 更新角色基本信息
                    role.Name = dto.Name;
                    role.NormalizedName = dto.Name.ToUpperInvariant();
                    role.Description = dto.Description;
                    role.ConcurrencyStamp = Guid.NewGuid().ToString();

                    await _roleRepository.UpdateAsync(role);

                    // 更新权限关联
                    await _roleRepository.SaveRolePermissionsAsync(role.Id, dto.PermissionIds ?? new List<Guid>());

                    await UnitOfWork.CommitTransactionAsync();
                }
                catch
                {
                    await UnitOfWork.RollbackTransactionAsync();
                    throw;
                }
            });

            return ApiResponse.Success();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "更新角色异常");
            throw;
        }
    }

    /// <summary>
    /// 删除角色
    /// </summary>
    /// <param name="id">角色ID</param>
    /// <returns>删除结果</returns>
    public async Task<ApiResponse> DeleteRoleAsync(Guid id)
    {
        // 获取角色
        var role = await _roleRepository.GetByIdAsync(id);
        if (role == null)
        {
            throw new BusinessException("角色不存在", SecurityErrorCodes.ROLE_NOT_FOUND);
        }

        // 系统角色不允许删除
        if (role.IsSystem)
        {
            throw new BusinessException("系统角色不允许删除", SecurityErrorCodes.SYSTEM_ROLE_DELETE_FORBIDDEN);
        }

        // 使用执行策略包装事务操作
        var strategy = UnitOfWork.CreateExecutionStrategy();
        await strategy.ExecuteAsync(async () =>
        {
            await UnitOfWork.BeginTransactionAsync();
            try
            {
                await _roleRepository.DeleteByIdAsync(id);
                await UnitOfWork.CommitTransactionAsync();
            }
            catch
            {
                await UnitOfWork.RollbackTransactionAsync();
                throw;
            }
        });

        return ApiResponse.Success();
    }

    /// <summary>
    /// 批量删除角色
    /// </summary>
    /// <param name="dto">批量删除参数</param>
    /// <returns>删除结果</returns>
    public async Task<ApiResponse<List<Guid>>> BatchDeleteRolesAsync(RoleBatchDeleteDto dto)
    {
        if (dto.RoleIds == null || !dto.RoleIds.Any())
        {
            throw new BusinessException("角色ID列表不能为空", BusinessErrorCodes.BusinessError);
        }

        // 检查是否包含系统角色
        var roles = await _roleRepository.GetListAsync(r => dto.RoleIds.Contains(r.Id));
        var systemRoleIds = roles.Where(r => r.IsSystem).Select(r => r.Id).ToList();

        if (systemRoleIds.Any())
        {
            throw new BusinessException("系统角色不允许删除", SecurityErrorCodes.SYSTEM_ROLE_DELETE_FORBIDDEN)
            {
                Data = { { "roleIds", systemRoleIds } }
            };
        }

        // 使用执行策略包装事务操作
        var strategy = UnitOfWork.CreateExecutionStrategy();
        var result = await strategy.ExecuteAsync(async () =>
        {
            await UnitOfWork.BeginTransactionAsync();
            try
            {
                var deletionResult = await _roleRepository.DeleteRolesAsync(dto.RoleIds);
                await UnitOfWork.CommitTransactionAsync();
                return deletionResult;
            }
            catch
            {
                await UnitOfWork.RollbackTransactionAsync();
                throw;
            }
        });

        if (result.Succeeded)
        {
            return ApiResponse<List<Guid>>.Success(result.FailedIds);
        }
        else
        {
            throw new BusinessException("部分角色删除失败", BusinessErrorCodes.BusinessError)
            {
                Data = { { "failedIds", result.FailedIds } }
            };
        }
    }

    /// <summary>
    /// 为角色分配用户
    /// </summary>
    /// <param name="dto">分配参数</param>
    /// <returns>分配结果</returns>
    public async Task<ApiResponse> AssignUsersToRoleAsync(RoleAssignUsersDto dto)
    {
        // 验证角色是否存在
        var role = await _roleRepository.GetByIdAsync(dto.RoleId);
        if (role == null)
        {
            throw new BusinessException("角色不存在", SecurityErrorCodes.ROLE_NOT_FOUND);
        }

        // 使用执行策略包装事务操作
        var strategy = UnitOfWork.CreateExecutionStrategy();
        var success = await strategy.ExecuteAsync(async () =>
        {
            await UnitOfWork.BeginTransactionAsync();
            try
            {
                var result = await _roleRepository.AssignUsersToRoleAsync(dto.RoleId, dto.UserIds);
                if (result)
                {
                    await UnitOfWork.CommitTransactionAsync();
                    return true;
                }
                else
                {
                    await UnitOfWork.RollbackTransactionAsync();
                    return false;
                }
            }
            catch
            {
                await UnitOfWork.RollbackTransactionAsync();
                throw;
            }
        });

        if (!success)
        {
            throw new BusinessException("角色分配用户失败", SecurityErrorCodes.ROLE_ASSIGN_USERS_FAILED);
        }

        return ApiResponse.Success();
    }

    /// <summary>
    /// 从角色中移除用户
    /// </summary>
    /// <param name="dto">移除参数</param>
    /// <returns>移除结果</returns>
    public async Task<ApiResponse> RemoveUsersFromRoleAsync(RoleAssignUsersDto dto)
    {
        // 验证角色是否存在
        var role = await _roleRepository.GetByIdAsync(dto.RoleId);
        if (role == null)
        {
            throw new BusinessException("角色不存在", SecurityErrorCodes.ROLE_NOT_FOUND);
        }

        // 使用执行策略包装事务操作
        var strategy = UnitOfWork.CreateExecutionStrategy();
        var success = await strategy.ExecuteAsync(async () =>
        {
            await UnitOfWork.BeginTransactionAsync();
            try
            {
                var result = await _roleRepository.RemoveUsersFromRoleAsync(dto.RoleId, dto.UserIds);
                if (result)
                {
                    await UnitOfWork.CommitTransactionAsync();
                    return true;
                }
                else
                {
                    await UnitOfWork.RollbackTransactionAsync();
                    return false;
                }
            }
            catch
            {
                await UnitOfWork.RollbackTransactionAsync();
                throw;
            }
        });

        if (!success)
        {
            throw new BusinessException("从角色移除用户失败", SecurityErrorCodes.ROLE_ASSIGN_USERS_FAILED);
        }

        return ApiResponse.Success();
    }

    /// <summary>
    /// 获取角色用户列表
    /// </summary>
    /// <param name="roleId">角色ID</param>
    /// <returns>用户列表</returns>
    public async Task<ApiResponse<IList<User>>> GetUsersInRoleAsync(Guid roleId)
    {
        // 验证角色是否存在
        var role = await _roleRepository.GetByIdAsync(roleId);
        if (role == null)
        {
            return ApiResponse<IList<User>>.Error(SecurityErrorCodes.ROLE_NOT_FOUND);
        }

        var users = await _roleRepository.GetUsersInRoleAsync(roleId);
        return ApiResponse<IList<User>>.Success(users);
    }

    /// <summary>
    /// 获取角色选择列表
    /// </summary>
    /// <returns>角色选择列表</returns>
    public async Task<ApiResponse<List<RoleSelectDto>>> GetRoleSelectListAsync()
    {
        var roles = await _roleRepository.GetRoleSelectListAsync();
        return ApiResponse<List<RoleSelectDto>>.Success(roles);
    }

    /// <summary>
    /// 检查角色名是否存在
    /// </summary>
    /// <param name="roleName">角色名称</param>
    /// <param name="excludeRoleId">排除的角色ID</param>
    /// <returns>是否存在</returns>
    public async Task<ApiResponse<bool>> IsRoleNameExistsAsync(string roleName, Guid? excludeRoleId = null)
    {
        var exists = await _roleRepository.ExistsByNameAsync(roleName, excludeRoleId);
        return ApiResponse<bool>.Success(exists);
    }
}